#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <cassert>
#include <ctime>
#include <sys/wait.h>
using namespace std;

#define PROCESS_NUM 5
#define MakeSeed() srand((unsigned long)time(nullptr)^getpid()^0x17923^rand()%1234)

///////////////////////////////////子进程要完成的某种任务-- 模拟一下/////////
// 函数指针 类型
typedef void (*func_t)();

void downLoadTask()
{
    std::cout << "下载任务" << std::endl;
    sleep(1);
}

void ioTask()
{
    cout << "IO任务" << std::endl;
    sleep(1);
}

void flushTask()
{
    cout << "刷新任务" << std::endl;
    sleep(1);
}

void LoadTaskFunc(std::vector<func_t> *out)
{
    assert(out);
    out->push_back(downLoadTask);
    out->push_back(ioTask);
    out->push_back(flushTask);
}

/////////////////////////////////下面的代码是一个多进程程序///////////////
class subEp // Endpoint
{
private:
    /* data */
    std::string name_;
    pid_t subId_;
    int writeFd_;
    static int num;

public:
    subEp(pid_t subId, int writeFd);
    string getName()const
    {
        return name_;
    }
    pid_t getWriteFd()const
    {
        return writeFd_;
    }
    ~subEp();
};
int subEp::num = 0;

subEp::subEp(pid_t subId, int writeFd)
    : subId_(subId), writeFd_(writeFd)
{
    char nameBuffer[1024];
    snprintf(nameBuffer, sizeof nameBuffer, "process-%d[pid(%d)-fd(%d)]", num++, subId_, writeFd_);
    name_ = nameBuffer;
    ++num;
}

subEp::~subEp()
{
}

void createSubProcess(std::vector<subEp> *subs, std::vector<func_t> &funcMap)
{
    for (int i = 0; i < PROCESS_NUM; ++i)
    {
        int fds[2];
        int n = pipe(fds);
        assert(n == 0);
        (void)n;
        // bug?
        pid_t id = fork();
        if (id == 0)
        {
            // 子进程,进行处理任务
            close(fds[1]);
            //1.获取命令码,如果没有发送,我们子进程应该阻塞
            //2.完成任务

            exit(0);
        }
        close(fds[0]);
        subEp sub(id, fds[1]);
        subs->push_back(sub);
    }
}

void sendTask(const subEp& process,int taskNum)
{
    std::cout<< "send task num:" << taskNum << " send to ->" << process.getName() << std::endl;
    int n = write(process.getWriteFd(),&taskNum,sizeof(taskNum));
    assert(n == sizeof(int));
    (void)n;
}

// void makeRandSeed()
// {
//     srand((unsigned long)time(nullptr));
// }

int main()
{
    MakeSeed();
    // 1.建立子进程并建立和子进程通信的信道,有bug的,但是不影响我们后面写
    //[子进程id,wfd]
    std::vector<func_t> funcMap;
    LoadTaskFunc(&funcMap);
    //
    std::vector<subEp> subs;

    createSubProcess(&subs, funcMap);

    // 2.走到这里就是父进程,控制子进程
    int processnum = subs.size();
    int tasknum = funcMap.size();
    bool quit = false;
    while (!quit)
    {
        // 1.选择一个子进程 -->std::vector<subEp> -> index - 随机数
        int subIdx = rand() % processnum;
        // 2.选择一个任务 --> std::vector<func_t> -> index
        int taskIdx = rand() % tasknum; 
        // 3.任务发送给选择的进程
        sendTask(subs[subIdx],taskIdx);
    }

    // 3.回收子进程信息

    return 0;
}